home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / telecomm / zmdm.zoo / zm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-27  |  21.2 KB  |  1,085 lines

  1. /*
  2.  *                ACKNOWLEDGEMENTS
  3.  *
  4.  *    ZMDM was derived from rz/sz for Unix  posted by 
  5.  *    Chuck Forsberg (...!tektronix!reed!omen!caf ). We
  6.  *    thank him for his excellent code, and for giving
  7.  *    us permission to use and distribute his code and
  8.  *    documentation.
  9.  *
  10.  *    Atari St version by:
  11.  *        Jwahar Bammi
  12.  * bang:   uunet!cadence!bammi
  13.  * domain: bammi@cadence.com
  14.  * GEnie:    J.Bammi
  15.  * CIS:    71515,155
  16.  */
  17.  
  18. /*
  19.  *   Z M . C
  20.  *    ZMODEM protocol primitives
  21.  *    05-24-89  Chuck Forsberg Omen Technology Inc
  22.  *
  23.  * Entry point Functions:
  24.  *    zsbhdr(type, hdr) send binary header
  25.  *    zshhdr(type, hdr) send hex header
  26.  *    zgethdr(hdr, eflag) receive header - binary or hex
  27.  *    zsdata(buf, len, frameend) send data
  28.  *    zrdata(buf, len) receive data
  29.  *    stohdr(pos) store position data in Txhdr
  30.  *    long rclhdr(hdr) recover position offset from header
  31.  *
  32.  *    This version implements ZMODEM Run Length Encoding, Comparision,
  33.  *    and variable length headers.  These features were not funded
  34.  *    by the original Telenet development contract.  This software,
  35.  *    including these features, may be freely used for non
  36.  *    commercial and educational purposes.  This software may also
  37.  *    be freely used to support file transfer operations to or from
  38.  *    licensed Omen Technology products.  Contact Omen Technology
  39.  *    for licensing for other uses.  Any programs which use part or
  40.  *    all of this software must be provided in source form with this
  41.  *    notice intact except by written permission from Omen
  42.  *    Technology Incorporated.
  43.  *
  44.  *        Omen Technology Inc        FAX: 503-621-3745
  45.  *        Post Office Box 4681
  46.  *        Portland OR 97208
  47.  *
  48.  *    Previous versions of this program (not containing the extensions
  49.  *    listed above) remain in the public domain.
  50.  *
  51.  *    This code is made available in the hope it will be useful,
  52.  *    BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
  53.  *    DAMAGES OF ANY KIND.
  54.  *
  55.  */
  56. #include "config.h"
  57. #include "zmdm.h"
  58. #include "common.h"
  59.  
  60. #ifndef CANFDX
  61. #include "zmodem.h"
  62. #endif
  63.  
  64. #define xsendline(X) sendline(X)
  65.  
  66. static char *badcrc = "Bad CRC";
  67. static lastsent;    /* Last char we sent */
  68. static Not8bit;        /* Seven bits seen on header */
  69. static char *frametypes[] = {
  70.     "No Response to Error Correction Request",    /* -4 */
  71.     "Carrier Lost",        /* -3 */
  72.     "TIMEOUT",        /* -2 */
  73.     "ERROR",        /* -1 */
  74. #define FTOFFSET 3
  75.     "ZRQINIT",
  76.     "ZRINIT",
  77.     "ZSINIT",
  78.     "ZACK",
  79.     "ZFILE",
  80.     "ZSKIP",
  81.     "ZNAK",
  82.     "ZABORT",
  83.     "ZFIN",
  84.     "ZRPOS",
  85.     "ZDATA",
  86.     "ZEOF",
  87.     "ZFERR",
  88.     "ZCRC",
  89.     "ZCHALLENGE",
  90.     "ZCOMPL",
  91.     "ZCAN",
  92.     "ZFREECNT",
  93.     "ZCOMMAND",
  94.     "ZSTDERR",
  95.     "xxxxx"
  96. #define FRTYPES 22    /* Total number of frame types in this array */
  97.             /*  not including psuedo negative entries */
  98. };
  99.  
  100. #define flushmo flush_modem
  101.  
  102. /* Send ZMODEM binary header hdr of type type */
  103. void zsbhdr(len, type, hdr)
  104. int len, type;
  105. register char *hdr;
  106. {
  107.     register int n;
  108.     register unsigned short crc;
  109.  
  110. #ifndef DSZ
  111.     vfile2("zsbhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  112.       frametypes[type+FTOFFSET], rclhdr(hdr));
  113. #endif
  114.     if (type == ZDATA)
  115.         for (n = Znulls; --n >=0; )
  116.             xsendline(0);
  117.  
  118.     xsendline(ZPAD); xsendline(ZDLE);
  119.  
  120.     switch (Crc32t=Txfcs32) {
  121.     case 2:
  122.         zsbh32(len, hdr, type, Usevhdrs?ZVBINR32:ZBINR32);
  123.         flushmo();  break;
  124.     case 1:
  125.         zsbh32(len, hdr, type, Usevhdrs?ZVBIN32:ZBIN32);  break;
  126.     default:
  127.         if (Usevhdrs) {
  128.             xsendline(ZVBIN);
  129.             zsendline(len);
  130.         }
  131.         else
  132.             xsendline(ZBIN);
  133.         zsendline(type);
  134.         crc = updcrc(type, 0);
  135.  
  136.         for (n=len; --n >= 0; ++hdr) {
  137.             zsendline(*hdr);
  138.             crc = updcrc((0377& *hdr), crc);
  139.         }
  140.         crc = updcrc(0,updcrc(0,crc));
  141.         zsendline(crc>>8);
  142.         zsendline(crc);
  143.     }
  144.     if (type != ZDATA)
  145.         flushmo();
  146. }
  147.  
  148. /* Send ZMODEM binary header hdr of type type */
  149. void zsbh32(len, hdr, type, flavour)
  150. int len, type, flavour;
  151. register char *hdr;
  152. {
  153.     register int n;
  154.     register unsigned long crc;
  155.  
  156.     xsendline(flavour); 
  157.     if (Usevhdrs) 
  158.         zsendline(len);
  159.     zsendline(type);
  160.     crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
  161.  
  162.     for (n=len; --n >= 0; ++hdr) {
  163.         crc = UPDC32((0377 & *hdr), crc);
  164.         zsendline(*hdr);
  165.     }
  166.     crc = ~crc;
  167.     for (n=4; --n >= 0;) {
  168.         zsendline((unsigned int)crc);
  169.         crc >>= 8;
  170.     }
  171. }
  172.  
  173. /* Send ZMODEM HEX header hdr of type type */
  174. void zshhdr(len, type, hdr)
  175. int len, type;
  176. register char *hdr;
  177. {
  178.     register int n;
  179.     register unsigned int crc;
  180.  
  181. #ifndef DSZ
  182.     vfile2("zshhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  183.       frametypes[type+FTOFFSET], rclhdr(hdr));
  184. #endif
  185.     sendline(ZPAD); sendline(ZPAD); sendline(ZDLE);
  186.     if (Usevhdrs) {
  187.         sendline(ZVHEX);
  188.         zputhex(len);
  189.     }
  190.     else
  191.         sendline(ZHEX);
  192.     zputhex(type);
  193.     Crc32t = 0;
  194.  
  195.     crc = updcrc(type, 0);
  196.     for (n=len; --n >= 0; ++hdr) {
  197.         zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
  198.     }
  199.     crc = updcrc(0,updcrc(0,crc));
  200.     zputhex(crc>>8); zputhex(crc);
  201.  
  202.     /* Make it printable on remote machine */
  203.     sendline(015); sendline(0212);
  204.     /*
  205.      * Uncork the remote in case a fake XOFF has stopped data flow
  206.      */
  207.     if (type != ZFIN && type != ZACK)
  208.         sendline(021);
  209.     flushmo();
  210. }
  211.  
  212. /*
  213.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  214.  */
  215. static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
  216.  
  217. void zsdata(buf, length, frameend)
  218. register char *buf;
  219. int length, frameend;
  220. {
  221.     register unsigned short crc;
  222.  
  223. #ifndef DSZ
  224.     vfile2("zsdata: %d %s", length, Zendnames[frameend-ZCRCE&3]);
  225. #endif
  226.     switch (Crc32t) {
  227.     case 1:
  228.         zsda32(buf, length, frameend);  break;
  229.     case 2:
  230.         zsdar32(buf, length, frameend);  break;
  231.     default:
  232.         crc = 0;
  233.         for (;--length >= 0; ++buf) {
  234.             zsendline(*buf); crc = updcrc((0377 & *buf), crc);
  235.         }
  236.         xsendline(ZDLE); xsendline(frameend);
  237.         crc = updcrc(frameend, crc);
  238.  
  239.         crc = updcrc(0,updcrc(0,crc));
  240.         zsendline(crc>>8); zsendline(crc);
  241.     }
  242.     if (frameend == ZCRCW) {
  243.         xsendline(XON);  flushmo();
  244.     }
  245. }
  246.  
  247. void zsda32(buf, length, frameend)
  248. int length, frameend;
  249. register char *buf;
  250. {
  251.     register int c;
  252.     register unsigned long crc;
  253.  
  254.     crc = 0xFFFFFFFFL;
  255.     for (;--length >= 0; ++buf) {
  256.         c = *buf & 0377;
  257.         if (c & 0140)
  258.             xsendline(lastsent = c);
  259.         else
  260.             zsendline(c);
  261.         crc = UPDC32(c, crc);
  262.     }
  263.     xsendline(ZDLE); xsendline(frameend);
  264.     crc = UPDC32(frameend, crc);
  265.  
  266.     crc = ~crc;
  267.     for (c=4; --c >= 0;) {
  268.         zsendline((unsigned int)crc);  crc >>= 8;
  269.     }
  270. }
  271.  
  272. /*
  273.  * Receive array buf of max length with ending ZDLE sequence
  274.  *  and CRC.  Returns the ending character or error code.
  275.  *  NB: On errors may store length+1 bytes!
  276.  */
  277. int zrdata(buf, length)
  278. register char *buf;
  279. int length;
  280. {
  281.     register int c;
  282.     register unsigned short crc;
  283.     register char *end;
  284.     register int d;
  285.  
  286.     switch (Crc32r) {
  287.     case 1:
  288.         return zrdat32(buf, length);
  289.     case 2:
  290.         return zrdatr32(buf, length);
  291.     }
  292.  
  293.     crc = Rxcount = 0;  end = buf + length;
  294.     while (buf <= end) {
  295.         if ((c = zdlread()) & ~0377) {
  296. crcfoo:
  297.             switch (c) {
  298.             case GOTCRCE:
  299.             case GOTCRCG:
  300.             case GOTCRCQ:
  301.             case GOTCRCW:
  302.                 crc = updcrc((d=c)&0377, crc);
  303.                 if ((c = zdlread()) & ~0377)
  304.                     goto crcfoo;
  305.                 crc = updcrc(c, crc);
  306.                 if ((c = zdlread()) & ~0377)
  307.                     goto crcfoo;
  308.                 crc = updcrc(c, crc);
  309.                 if (crc & 0xFFFF) {
  310.                     log2(badcrc);
  311.                     return ERROR;
  312.                 }
  313.                 Rxcount = length - (end - buf);
  314. #ifndef DSZ
  315.                 vfile2("zrdata: %d  %s", Rxcount,
  316.                  Zendnames[d-GOTCRCE&3]);
  317. #endif
  318.                 return d;
  319.             case GOTCAN:
  320.                 log2("Sender Canceled");
  321.                 return ZCAN;
  322.             case TIMEOUT:
  323.                 log2("TIMEOUT");
  324.                 return c;
  325.             default:
  326.                 garbitch(); return c;
  327.             }
  328.         }
  329.         *buf++ = c;
  330.         crc = updcrc(c, crc);
  331.     }
  332. #ifdef DSZ
  333.     garbitch(); 
  334. #else
  335.     log2("Data subpacket too long");
  336. #endif
  337.     return ERROR;
  338. }
  339.  
  340. int zrdat32(buf, length)
  341. register char *buf;
  342. int length;
  343. {
  344.     register int c;
  345.     register unsigned long crc;
  346.     register char *end;
  347.     register int d;
  348.  
  349.     crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
  350.     while (buf <= end) {
  351.         if ((c = zdlread()) & ~0377) {
  352. crcfoo:
  353.             switch (c) {
  354.             case GOTCRCE:
  355.             case GOTCRCG:
  356.             case GOTCRCQ:
  357.             case GOTCRCW:
  358.                 d = c;  c &= 0377;
  359.                 crc = UPDC32(c, crc);
  360.                 if ((c = zdlread()) & ~0377)
  361.                     goto crcfoo;
  362.                 crc = UPDC32(c, crc);
  363.                 if ((c = zdlread()) & ~0377)
  364.                     goto crcfoo;
  365.                 crc = UPDC32(c, crc);
  366.                 if ((c = zdlread()) & ~0377)
  367.                     goto crcfoo;
  368.                 crc = UPDC32(c, crc);
  369.                 if ((c = zdlread()) & ~0377)
  370.                     goto crcfoo;
  371.                 crc = UPDC32(c, crc);
  372.                 if (crc != 0xDEBB20E3L) {
  373.                     log2(badcrc);
  374.                     return ERROR;
  375.                 }
  376.                 Rxcount = length - (end - buf);
  377. #ifndef DSZ
  378.                 vfile2("zrdat32: %d %s", Rxcount,
  379.                  Zendnames[d-GOTCRCE&3]);
  380. #endif
  381.                 return d;
  382.             case GOTCAN:
  383.                 log2("Sender Canceled");
  384.                 return ZCAN;
  385.             case TIMEOUT:
  386.                 log2("TIMEOUT");
  387.                 return c;
  388.             default:
  389.                 garbitch(); return c;
  390.             }
  391.         }
  392.         *buf++ = c;
  393.         crc = UPDC32(c, crc);
  394.     }
  395.     log2("Data subpacket too long");
  396.     return ERROR;
  397. }
  398.  
  399. void garbitch()
  400. {
  401.     log2("Garbled data subpacket");
  402. }
  403.  
  404. /*
  405.  * Read a ZMODEM header to hdr, either binary or hex.
  406.  *  eflag controls local display of non zmodem characters:
  407.  *    0:  no display
  408.  *    1:  display printing characters only
  409.  *    2:  display all non ZMODEM characters
  410.  *
  411.  *   Set Rxhlen to size of header (default 4) (valid iff good hdr)
  412.  *  On success, set Zmodem to 1, set Rxpos and return type of header.
  413.  *   Otherwise return negative on error.
  414.  *   Return ERROR instantly if ZCRCW sequence, for fast error recovery.
  415.  */
  416. int zgethdr(hdr, eflag)
  417. char *hdr;
  418. int eflag;
  419. {
  420.     register int c, n, cancount;
  421.  
  422.     n = Zrwindow + Baudrate;    /* Max bytes before start of frame */
  423.     Rxframeind = Rxtype = 0;
  424.  
  425. startover:
  426.     cancount = 5;
  427. again:
  428.     /* Return immediate ERROR if ZCRCW sequence seen */
  429.     switch (c = readline(Rxtimeout)) {
  430.     case RCDO:
  431.     case TIMEOUT:
  432.         goto fifi;
  433.     case CAN:
  434. gotcan:
  435.         if (--cancount <= 0) {
  436.             c = ZCAN; goto fifi;
  437.         }
  438.         switch (c = readline(1)) {
  439.         case TIMEOUT:
  440.             goto again;
  441.         case ZCRCW:
  442.             switch (readline(1)) {
  443.             case TIMEOUT:
  444.                 c = ERROR; goto fifi;
  445.             case RCDO:
  446.                 goto fifi;
  447.             default:
  448.                 goto agn2;
  449.             }
  450.         case RCDO:
  451.             goto fifi;
  452.         default:
  453.             break;
  454.         case CAN:
  455.             if (--cancount <= 0) {
  456.                 c = ZCAN; goto fifi;
  457.             }
  458.             goto again;
  459.         }
  460.     /* **** FALL THRU TO **** */
  461.     default:
  462. agn2:
  463.         if ( --n == 0) {
  464.             c = GCOUNT;  goto fifi;
  465.         }
  466.         if (eflag && ((c &= 0177) & 0140))
  467.             bttyout(c);
  468.         else if (eflag > 1)
  469.             bttyout(c);
  470. #ifdef UNIX
  471.         fflush(stderr);
  472. #endif
  473.         goto startover;
  474.     case ZPAD|0200:        /* This is what we want. */
  475.         Not8bit = c;
  476.     case ZPAD:        /* This is what we want. */
  477.         break;
  478.     }
  479.     cancount = 5;
  480. splat:
  481.     switch (c = noxrd7()) {
  482.     case ZPAD:
  483.         goto splat;
  484.     case RCDO:
  485.     case TIMEOUT:
  486.         goto fifi;
  487.     default:
  488.         goto agn2;
  489.     case ZDLE:        /* This is what we want. */
  490.         break;
  491.     }
  492.  
  493.  
  494.     Rxhlen = 4;        /* Set default length */
  495.     Rxframeind = c = noxrd7();
  496.     switch (c) {
  497.     case ZVBIN32:
  498.         if ((Rxhlen = c = zdlread()) < 0)
  499.             goto fifi;
  500.         if (c > ZMAXHLEN)
  501.             goto agn2;
  502.         Crc32r = 1;  c = zrbhd32(hdr); break;
  503.     case ZBIN32:
  504.         if (Usevhdrs)
  505.             goto agn2;
  506.         Crc32r = 1;  c = zrbhd32(hdr); break;
  507.     case ZVBINR32:
  508.         if ((Rxhlen = c = zdlread()) < 0)
  509.             goto fifi;
  510.         if (c > ZMAXHLEN)
  511.             goto agn2;
  512.         Crc32r = 2;  c = zrbhd32(hdr); break;
  513.     case ZBINR32:
  514.         if (Usevhdrs)
  515.             goto agn2;
  516.         Crc32r = 2;  c = zrbhd32(hdr); break;
  517.     case RCDO:
  518.     case TIMEOUT:
  519.         goto fifi;
  520.     case ZVBIN:
  521.         if ((Rxhlen = c = zdlread()) < 0)
  522.             goto fifi;
  523.         if (c > ZMAXHLEN)
  524.             goto agn2;
  525.         Crc32r = 0;  c = zrbhdr(hdr); break;
  526.     case ZBIN:
  527.         if (Usevhdrs)
  528.             goto agn2;
  529.         Crc32r = 0;  c = zrbhdr(hdr); break;
  530.     case ZVHEX:
  531.         if ((Rxhlen = c = zgethex()) < 0)
  532.             goto fifi;
  533.         if (c > ZMAXHLEN)
  534.             goto agn2;
  535.         Crc32r = 0;  c = zrhhdr(hdr); break;
  536.     case ZHEX:
  537.         if (Usevhdrs)
  538.             goto agn2;
  539.         Crc32r = 0;  c = zrhhdr(hdr); break;
  540.     case CAN:
  541.         goto gotcan;
  542.     default:
  543.         goto agn2;
  544.     }
  545.     Rxpos = hdr[ZP3] & 0377;
  546.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  547.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  548.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  549. fifi:
  550.     switch (c) {
  551.     case GOTCAN:
  552.         c = ZCAN;
  553.     /* **** FALL THRU TO **** */
  554.     case ZNAK:
  555.     case ZCAN:
  556.     case ERROR:
  557.     case TIMEOUT:
  558.     case RCDO:
  559.     case GCOUNT:
  560.         log2("Got %s", frametypes[c+FTOFFSET]);
  561.     /* **** FALL THRU TO **** */
  562. #ifndef DSZ
  563.     default:
  564.         if (c >= -4 && c <= FRTYPES)
  565.             vfile2("zgethdr: %c %d %s %lx", Rxframeind, Rxhlen,
  566.               frametypes[c+FTOFFSET], Rxpos);
  567.         else
  568.             vfile2("zgethdr: %c %d %lx", Rxframeind, c, Rxpos);
  569. #endif
  570.     }
  571.     /* Use variable length headers if we got one */
  572.     if (c >= 0 && c <= FRTYPES && Rxframeind & 040)
  573.         Usevhdrs = 1;
  574.     return c;
  575. }
  576.  
  577. /* Receive a binary style header (type and position) */
  578. int zrbhdr(hdr)
  579. register char *hdr;
  580. {
  581.     register int c, n;
  582.     register unsigned short crc;
  583.  
  584.     if ((c = zdlread()) & ~0377)
  585.         return c;
  586.     Rxtype = c;
  587.     crc = updcrc(c, 0);
  588.  
  589.     for (n=Rxhlen; --n >= 0; ++hdr) {
  590.         if ((c = zdlread()) & ~0377)
  591.             return c;
  592.         crc = updcrc(c, crc);
  593.         *hdr = c;
  594.     }
  595.     if ((c = zdlread()) & ~0377)
  596.         return c;
  597.     crc = updcrc(c, crc);
  598.     if ((c = zdlread()) & ~0377)
  599.         return c;
  600.     crc = updcrc(c, crc);
  601.     if (crc & 0xFFFF) {
  602.         log2(badcrc);
  603.         return ERROR;
  604.     }
  605. #ifdef ZMODEM
  606.     Protocol = ZMODEM;
  607. #endif
  608.     Zmodem = 1;
  609.     return Rxtype;
  610. }
  611.  
  612. /* Receive a binary style header (type and position) with 32 bit FCS */
  613. int zrbhd32(hdr)
  614. register char *hdr;
  615. {
  616.     register int c, n;
  617.     register unsigned long crc;
  618.  
  619.     if ((c = zdlread()) & ~0377)
  620.         return c;
  621.     Rxtype = c;
  622.     crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
  623. #ifdef DEBUGZ
  624.     vfile2("zrbhd32 c=%X  crc=%lX", c, crc);
  625. #endif
  626.  
  627.     for (n=Rxhlen; --n >= 0; ++hdr) {
  628.         if ((c = zdlread()) & ~0377)
  629.             return c;
  630.         crc = UPDC32(c, crc);
  631.         *hdr = c;
  632. #ifdef DEBUGZ
  633.         vfile2("zrbhd32 c=%X  crc=%lX", c, crc);
  634. #endif
  635.     }
  636.     for (n=4; --n >= 0;) {
  637.         if ((c = zdlread()) & ~0377)
  638.             return c;
  639.         crc = UPDC32(c, crc);
  640. #ifdef DEBUGZ
  641.         vfile2("zrbhd32 c=%X  crc=%lX", c, crc);
  642. #endif
  643.     }
  644.     if (crc != 0xDEBB20E3L) {
  645.         log2(badcrc);
  646.         return ERROR;
  647.     }
  648. #ifdef ZMODEM
  649.     Protocol = ZMODEM;
  650. #endif
  651.     Zmodem = 1;
  652.     return Rxtype;
  653. }
  654.  
  655.  
  656. /* Receive a hex style header (type and position) */
  657. int zrhhdr(hdr)
  658. char *hdr;
  659. {
  660.     register int c;
  661.     register unsigned short crc;
  662.     register int n;
  663.  
  664.     if ((c = zgethex()) < 0)
  665.         return c;
  666.     Rxtype = c;
  667.     crc = updcrc(c, 0);
  668.  
  669.     for (n=Rxhlen; --n >= 0; ++hdr) {
  670.         if ((c = zgethex()) < 0)
  671.             return c;
  672.         crc = updcrc(c, crc);
  673.         *hdr = c;
  674.     }
  675.     if ((c = zgethex()) < 0)
  676.         return c;
  677.     crc = updcrc(c, crc);
  678.     if ((c = zgethex()) < 0)
  679.         return c;
  680.     crc = updcrc(c, crc);
  681.     if (crc & 0xFFFF) {
  682.         log2(badcrc); return ERROR;
  683.     }
  684.     switch ( c = readline(1)) {
  685.     case 0215:
  686.         Not8bit = c;
  687.         /* **** FALL THRU TO **** */
  688.     case 015:
  689.          /* Throw away possible cr/lf */
  690.         switch (c = readline(1)) {
  691.         case 012:
  692.             Not8bit |= c;
  693.         }
  694.     }
  695. #ifdef ZMODEM
  696.     Protocol = ZMODEM;
  697. #endif
  698.     Zmodem = 1; return Rxtype;
  699. }
  700.  
  701. /* Send a byte as two hex digits */
  702. void zputhex(c)
  703. register int c;
  704. {
  705.     static char    digits[]    = "0123456789abcdef";
  706.  
  707. #ifdef DEBUGZ
  708.     if (Verbose>8)
  709.         vfile2("zputhex: %02X", c);
  710. #endif
  711.     sendline(digits[(((unsigned int)c&0xF0))>>4]);
  712.     sendline(digits[(c)&0xF]);
  713. }
  714.  
  715. /*
  716.  * Send character c with ZMODEM escape sequence encoding.
  717.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  718.  */
  719. void zsendline(c)
  720. int c;
  721. {
  722.  
  723.     /* Quick check for non control characters */
  724.     if (c & 0140)
  725.         xsendline(lastsent = c);
  726.     else {
  727.         switch (c &= 0377) {
  728.         case ZDLE:
  729.             xsendline(ZDLE);
  730.             xsendline (lastsent = (c ^= 0100));
  731.             break;
  732.         case 015:
  733.         case 0215:
  734.             if (!Zctlesc && (lastsent & 0177) != '@')
  735.                 goto sendit;
  736.         /* **** FALL THRU TO **** */
  737.         case 020:
  738.         case 021:
  739.         case 023:
  740.         case 0220:
  741.         case 0221:
  742.         case 0223:
  743.             xsendline(ZDLE);
  744.             c ^= 0100;
  745.     sendit:
  746.             xsendline(lastsent = c);
  747.             break;
  748.         default:
  749.             if (Zctlesc && ! (c & 0140)) {
  750.                 xsendline(ZDLE);
  751.                 c ^= 0100;
  752.             }
  753.             xsendline(lastsent = c);
  754.         }
  755.     }
  756. }
  757.  
  758. /* Decode two lower case hex digits into an 8 bit byte value */
  759. int zgethex()
  760. {
  761.     register int c;
  762.  
  763.     c = zgeth1();
  764. #ifdef DEBUGZ
  765.     if (Verbose>8)
  766.         vfile2("zgethex: %02X", c);
  767. #endif
  768.     return c;
  769. }
  770.  
  771. int zgeth1()
  772. {
  773.     register int c, n;
  774.  
  775.     if ((c = noxrd7()) < 0)
  776.         return c;
  777.     n = c - '0';
  778.     if (n > 9)
  779.         n -= ('a' - ':');
  780.     if (n & ~0xF)
  781.         return ERROR;
  782.     if ((c = noxrd7()) < 0)
  783.         return c;
  784.     c -= '0';
  785.     if (c > 9)
  786.         c -= ('a' - ':');
  787.     if (c & ~0xF)
  788.         return ERROR;
  789.     c += (n<<4);
  790.     return c;
  791. }
  792.  
  793. /*
  794.  * Read a byte, checking for ZMODEM escape encoding
  795.  *  including CAN*5 which represents a quick abort
  796.  */
  797. int zdlread()
  798. {
  799.     register int c;
  800.  
  801. again:
  802.     /* Quick check for non control characters */
  803.     if ((c = readline(Rxtimeout)) & 0140)
  804.         return c;
  805.     switch (c) {
  806.     case ZDLE:
  807.         break;
  808.     case 023:
  809.     case 0223:
  810.     case 021:
  811.     case 0221:
  812.         goto again;
  813.     default:
  814.         if (Zctlesc && !(c & 0140)) {
  815.             goto again;
  816.         }
  817.         return c;
  818.     }
  819. again2:
  820.     if ((c = readline(Rxtimeout)) < 0)
  821.         return c;
  822.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  823.         return c;
  824.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  825.         return c;
  826.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  827.         return c;
  828.     switch (c) {
  829.     case CAN:
  830.         return GOTCAN;
  831.     case ZCRCE:
  832.     case ZCRCG:
  833.     case ZCRCQ:
  834.     case ZCRCW:
  835.         return (c | GOTOR);
  836.     case ZRUB0:
  837.         return 0177;
  838.     case ZRUB1:
  839.         return 0377;
  840.     case 023:
  841.     case 0223:
  842.     case 021:
  843.     case 0221:
  844.         goto again2;
  845.     default:
  846.         if (Zctlesc && ! (c & 0140)) {
  847.             goto again2;
  848.         }
  849.         if ((c & 0140) ==  0100)
  850.             return (c ^ 0100);
  851.         break;
  852.     }
  853.     if (Verbose>1)
  854.         log2("Bad escape sequence %x", c);
  855.     return ERROR;
  856. }
  857.  
  858. /*
  859.  * Read a character from the modem line with timeout.
  860.  *  Eat parity, XON and XOFF characters.
  861.  */
  862. int noxrd7()
  863. {
  864.     register int c;
  865.  
  866.     for (;;) {
  867.         if ((c = readline(Rxtimeout)) < 0)
  868.             return c;
  869.         switch (c &= 0177) {
  870.         case XON:
  871.         case XOFF:
  872.             continue;
  873.         default:
  874.             if (Zctlesc && !(c & 0140))
  875.                 continue;
  876.         case '\r':
  877.         case '\n':
  878.         case ZDLE:
  879.             return c;
  880.         }
  881.     }
  882. }
  883.  
  884. /* Store long integer pos in Txhdr */
  885. void stohdr(p)
  886. long p;
  887. {
  888.     unsigned long pos = p;
  889.     
  890.     Txhdr[ZP0] = pos;
  891.     Txhdr[ZP1] = pos>>8;
  892.     Txhdr[ZP2] = pos>>16;
  893.     Txhdr[ZP3] = pos>>24;
  894. }
  895.  
  896. /* Recover a long integer from a header */
  897. long
  898. rclhdr(hdr)
  899. register char *hdr;
  900. {
  901.     register long l;
  902.  
  903.     l = (hdr[ZP3] & 0377);
  904.     l = (l << 8) | (hdr[ZP2] & 0377);
  905.     l = (l << 8) | (hdr[ZP1] & 0377);
  906.     l = (l << 8) | (hdr[ZP0] & 0377);
  907.     return l;
  908. }
  909.  
  910. /*
  911.  * File: zmr.c 12-04-1988
  912.  * Copyright 1988 Omen Technology Inc All Rights Reserved
  913.  *
  914.  *
  915.  *    This code implements ZMODEM Run Length Encoding, not funded
  916.  *    by the original Telenet development contract.  This software,
  917.  *    including these features, may be freely used for non
  918.  *    commercial and educational purposes.  This software may also
  919.  *    be freely used to support file transfer operations to or from
  920.  *    licensed Omen Technology products.  Contact Omen Technology
  921.  *    for licensing for other uses.  Any programs which use part or
  922.  *    all of this software must be provided in source form with this
  923.  *    notice intact except by written permission from Omen
  924.  *    Technology Incorporated.
  925.  *
  926.  *        Omen Technology Inc        FAX: 503-621-3745
  927.  *        Post Office Box 4681
  928.  *        Portland OR 97208
  929.  *
  930.  *    This code is made available in the hope it will be useful,
  931.  *    BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
  932.  *    DAMAGES OF ANY KIND.
  933.  *    ZMODEM RLE compression and decompression functions
  934.  */
  935.  
  936. /* Send data subpacket RLE encoded with 32 bit FCS */
  937. void zsdar32(buf, length, frameend)
  938. char *buf;
  939. int length, frameend;
  940. {
  941.     register int c, l, n;
  942.     register unsigned long crc;
  943.  
  944.     crc = 0xFFFFFFFFL;  l = *buf++ & 0377;
  945.     if (length == 1) {
  946.         zsendline(l); crc = UPDC32(l, crc);
  947.         if (l == ZRESC) {
  948.             zsendline(1); crc = UPDC32(1, crc);
  949.         }
  950.     } else {
  951.         for (n = 0; --length >= 0; ++buf) {
  952.             if ((c = *buf & 0377) == l && n < 126 && length>0) {
  953.                 ++n;  continue;
  954.             }
  955.             switch (n) {
  956.             case 0:
  957.                 zsendline(l);
  958.                 crc = UPDC32(l, crc);
  959.                 if (l == ZRESC) {
  960.                     zsendline(0100); crc = UPDC32(0100, crc);
  961.                 }
  962.                 l = c; break;
  963.             case 1:
  964.                 if (l != ZRESC) {
  965.                     zsendline(l); zsendline(l);
  966.                     crc = UPDC32(l, crc);
  967.                     crc = UPDC32(l, crc);
  968.                     n = 0; l = c; break;
  969.                 }
  970.                 /* **** FALL THRU TO **** */
  971.             default:
  972.                 zsendline(ZRESC); crc = UPDC32(ZRESC, crc);
  973.                 if (l == 040 && n < 34) {
  974.                     n += 036;
  975.                     zsendline(n); crc = UPDC32(n, crc);
  976.                 }
  977.                 else {
  978.                     n += 0101;
  979.                     zsendline(n); crc = UPDC32(n, crc);
  980.                     zsendline(l); crc = UPDC32(l, crc);
  981.                 }
  982.                 n = 0; l = c; break;
  983.             }
  984.         }
  985.     }
  986.     xsendline(ZDLE); xsendline(frameend);
  987.     crc = UPDC32(frameend, crc);
  988.  
  989.     crc = ~crc;
  990.     for (length=4; --length >= 0;) {
  991.         zsendline((unsigned int)crc);  crc >>= 8;
  992.     }
  993. }
  994.  
  995.  
  996. /* Receive data subpacket RLE encoded with 32 bit FCS */
  997. int zrdatr32(buf, length)
  998. register char *buf;
  999. int length;
  1000. {
  1001.     register int c;
  1002.     register unsigned long crc;
  1003.     register char *end;
  1004.     register int d;
  1005.  
  1006.     crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
  1007.     d = 0;    /* Use for RLE decoder state */
  1008.     while (buf <= end) {
  1009.         if ((c = zdlread()) & ~0377) {
  1010. crcfoo:
  1011.             switch (c) {
  1012.             case GOTCRCE:
  1013.             case GOTCRCG:
  1014.             case GOTCRCQ:
  1015.             case GOTCRCW:
  1016.                 d = c;  c &= 0377;
  1017.                 crc = UPDC32(c, crc);
  1018.                 if ((c = zdlread()) & ~0377)
  1019.                     goto crcfoo;
  1020.                 crc = UPDC32(c, crc);
  1021.                 if ((c = zdlread()) & ~0377)
  1022.                     goto crcfoo;
  1023.                 crc = UPDC32(c, crc);
  1024.                 if ((c = zdlread()) & ~0377)
  1025.                     goto crcfoo;
  1026.                 crc = UPDC32(c, crc);
  1027.                 if ((c = zdlread()) & ~0377)
  1028.                     goto crcfoo;
  1029.                 crc = UPDC32(c, crc);
  1030.                 if (crc != 0xDEBB20E3L) {
  1031.                     log2(badcrc);
  1032.                     return ERROR;
  1033.                 }
  1034.                 Rxcount = length - (end - buf);
  1035. #ifndef DSZ
  1036.                 vfile2("zrdatr32: %d %s", Rxcount,
  1037.                   Zendnames[d-GOTCRCE&3]);
  1038. #endif
  1039.                 return d;
  1040.             case GOTCAN:
  1041.                 log2("Sender Canceled");
  1042.                 return ZCAN;
  1043.             case TIMEOUT:
  1044.                 log2("TIMEOUT");
  1045.                 return c;
  1046.             default:
  1047.                 log2("Bad data subpacket");
  1048.                 return c;
  1049.             }
  1050.         }
  1051.         crc = UPDC32(c, crc);
  1052.         switch (d) {
  1053.         case 0:
  1054.             if (c == ZRESC) {
  1055.                 d = -1;  continue;
  1056.             }
  1057.             *buf++ = c;  continue;
  1058.         case -1:
  1059.             if (c >= 040 && c < 0100) {
  1060.                 d = c - 035; c = 040;  goto spaces;
  1061.             }
  1062.             if (c == 0100) {
  1063.                 d = 0;
  1064.                 *buf++ = ZRESC;  continue;
  1065.             }
  1066.             d = c;  continue;
  1067.         default:
  1068.             d -= 0100;
  1069.             if (d < 1)
  1070.                 goto badpkt;
  1071. spaces:
  1072.             if ((buf + d) > end)
  1073.                 goto badpkt;
  1074.             while ( --d >= 0)
  1075.                 *buf++ = c;
  1076.             d = 0;  continue;
  1077.         }
  1078.     }
  1079. badpkt:
  1080.     log2("Data subpacket too long");
  1081.     return ERROR;
  1082. }
  1083.  
  1084. /* -eof- */
  1085.